from utils.checksum import ChecksumInfo
import fnv,os
import re
from files.package_pool import *
from typing import List,Dict
class PackageFile(object):
    Filename=''
    Checksums:ChecksumInfo=None
    PoolPath=''
    downloadPath=''
    def __init__(self) -> None:
        self.Checksums=ChecksumInfo()
    def Verify(f ,packagePool , checksumStorage ) :
        generatedPoolPath, exists= packagePool.Verify(f.PoolPath, f.Filename, f.Checksums, checksumStorage)
        if exists  :
            f.PoolPath = generatedPoolPath

        return exists


    # // GetPoolPath returns path to the file in the pool
    # //
    # // For legacy packages which do not have PoolPath field set, that calculates LegacyPath via pool
    def GetPoolPath(f,packagePool):

        if f.PoolPath == "" :
            f.PoolPath = packagePool.LegacyPath(f.Filename, f.Checksums)

        return f.PoolPath


    # // DownloadURL return relative URL to package download location
    def DownloadURL(f):
        return os.path.join(f.downloadPath, f.Filename)


    # // PackageFiles is collection of package files
    # type PackageFiles []PackageFile
class PackageFiles(list):
    def __init__(self) -> None:
        pass
    # // Hash compute hash of all file items, sorting them first
    def Hash(self) :
        byteBuff=bytearray()
        
        for  f in self :
        
            byteBuff+=(f.Filename.encode())
        
            byteBuff+=(f.Checksums.Size.to_bytes(f.Checksums.Size,'big'))
            byteBuff+=(f.Checksums.MD5.encode())
            byteBuff+=(f.Checksums.SHA1.encode())
            byteBuff+=(f.Checksums.SHA256.encode())
        # print(byteBuff)
        return fnv.hash(byteBuff,bits=64)


    # // Len returns number of files
    def Len(self) :
        return len(self.files)


    # // Swap swaps elements
    def Swap(self,i, j ):
        self.files[i], self.files[j] = self.files[j], self.files[i]


    # // Less compares by filename
    def Less(self,i, j ) :
        return self.files[i].Filename < self.files[j].Filename


    # // ParseSumField populates PackageFiles by parsing given input
    def ParseSumField(self,input , setter , withSize , onlyBasePath ) :

        for line in input.split(input, "\n") :
            line = line.strip()
            if line == "" :
                continue
            
            parts = re.split(r'\s',line)#空白符切片

            if withSize and len(parts) < 3 or not withSize and len(parts) < 2 :
                print(("unparseable hash sum line: %#v", line))
                return None
            


            if withSize :
                size= int(parts[1])
                

            filename = parts[len(parts)-1]
            if onlyBasePath :
                filename = os.path.basename(filename)
            

            found = False
            pos = 0

            for i in range(len(self.files)) :
                file=self.files[i]
                if file.Filename == filename :
                    found = True
                    pos = i
                    break
            

            if not found :
                packagefile=PackageFile()
                packagefile.Filename=filename
                self.files = self.files.append( packagefile)
                pos = len(self.files) - 1
            

            self.files[pos].Checksums.Size = size
            setter(self.files[pos].Checksums, parts[0])
        

        return self.files


    # // ParseSumFields populates PackageFiles by parsing stanza checksums fields
    def ParseSumFields(self,stanza):
        # def computeMd5(sum,data):
        #     sum.MD5=data
        # def computeSha1(sum,data):
        #     sum.Sha1=data
        # def computeSha256(sum,data):
        #     sum.Sha256=data
        # def computeSha512(sum,data):
        #     sum.Sha512=data
        files = self.ParseSumField(files,stanza.data["Files"],lambda sum,data:setattr(sum,'MD5',data), True, True)
        

        files = self.ParseSumField(files,stanza.data["Checksums-Sha1"], lambda sum,data:setattr(sum,'Sha1',data), True, True)
        

        files = self.ParseSumField(files,stanza.data["Checksums-Sha256"], lambda sum,data:setattr(sum,'Sha256',data), True, True)
        

        files = self.ParseSumField(files,stanza.data["Checksums-Sha512"], lambda sum,data:setattr(sum,'Sha512',data), True, True)

        return files
